package com.suos.core;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.system.HostInfo;
import cn.hutool.system.JvmInfo;
import cn.hutool.system.OsInfo;
import cn.hutool.system.SystemUtil;
import cn.hutool.system.oshi.CpuInfo;
import cn.hutool.system.oshi.OshiUtil;
import com.suos.conf.SuOsProperties;
import com.suos.core.entity.*;
import com.suos.core.utils.PriUtil;
import org.springframework.beans.factory.annotation.Value;
import oshi.SystemInfo;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;

import java.util.LinkedList;
import java.util.List;

/**
 * SugarOshi 信息获取
 *
 * @author : MisShi
 * @date: 2021-10-21 15:03:03
 */

public class SugarOshi {


    @Value("${sugar.oshi.unbid:''}")
    private String unbid;

    private final SuOsProperties suOsProperties;

    public SugarOshi(SuOsProperties suOsProperties) {
        this.suOsProperties = suOsProperties;
    }

    /***
     * 多模块获取系统信息
     *
     * @return 多个服务器信息
     */
    private List<SysInfo> getSysInfos() {
        return PriUtil.sysInfos;
    }

    /**
     * 单机版获取系统信息
     *
     * @return 服务器信息
     */
    public SysInfo getSysInfo() {
        SysInfo sysInfo = new SysInfo();
        sysInfo.setUnbid(unbid);
        SystemInfo systemInfo = new SystemInfo();
        HardwareAbstractionLayer hardware = systemInfo.getHardware();
        sysInfo.setJvm(getJvmInfo());
        sysInfo.setOs(getOsInfo(systemInfo.getOperatingSystem()));
        // TODO 是否考虑 异步
        sysInfo.setCpu(this.getCpuInfo());
        sysInfo.setMemory(getMemoryInfo(hardware.getMemory()));
        sysInfo.setDisks(getDisksInfo(systemInfo.getOperatingSystem()));
        // TODO 是否需要 待定 sysInfo.setProject(getProjectInfo());
        return sysInfo;
    }

    /**
     * 设置 JVM 信息
     */
    private Jvm getJvmInfo() {
        Jvm jvm = new Jvm();
        JvmInfo jvmInfo = SystemUtil.getJvmInfo();
        Runtime runtime = Runtime.getRuntime();
        jvm.setName(jvmInfo.getName());
        jvm.setVersion(SystemUtil.getJvmSpecInfo().getVersion());
        jvm.setDetailVersion(jvmInfo.getVersion());
        jvm.setVendor(jvmInfo.getVendor());
        jvm.setHomeDir(SystemUtil.getJavaRuntimeInfo().getHomeDir());
        jvm.setTotalOcMem(PriUtil.jcmSize(runtime.totalMemory()));
        jvm.setMaxAvaMem(PriUtil.jcmSize(runtime.maxMemory()));
        jvm.setFreeMem(PriUtil.jcmSize(runtime.freeMemory()));
        return jvm;
    }

    /**
     * 设置 OS 信息
     *
     * @param operatingSystem 操作系统
     */
    private Os getOsInfo(OperatingSystem operatingSystem) {
        Os os = new Os();
        HostInfo hostInfo = SystemUtil.getHostInfo();
        OsInfo osInfo = SystemUtil.getOsInfo();
        os.setOsName(operatingSystem.getFamily() + " " + operatingSystem.getVersionInfo().getVersion());
        os.setOsArch(osInfo.getArch());
        os.setOsBitness(operatingSystem.getBitness());
        os.setOsVersion(operatingSystem.getVersionInfo().toString());
        os.setOsVendor(operatingSystem.getManufacturer());
        os.setHostName(hostInfo.getName());
        os.setHostAddress(hostInfo.getAddress());
        os.setOsBootTime(DateUtil.format(DateUtil.date(operatingSystem.getSystemBootTime() * 1000L), "yyyy年MM月dd日 HH时mm分ss秒"));
        os.setOsUptime(DateUtil.formatBetween(operatingSystem.getSystemUptime() * 1000L));
        return os;
    }

    /**
     * 设置 CPU 信息
     */
    private Cpu getCpuInfo() {
        Cpu cpu = new Cpu();
        CpuInfo cpuInfo = OshiUtil.getCpuInfo(suOsProperties.getWaitSecond());
        cpu.setCpuNum(cpuInfo.getCpuNum());
        cpu.setCpuModel(cpuInfo.getCpuModel());
        cpu.setToTal(cpuInfo.getToTal() + "%");
        cpu.setSys(cpuInfo.getSys() + "%");
        cpu.setUsed(cpuInfo.getUsed() + "%");
        cpu.setFree(cpuInfo.getFree() + "%");
        cpu.setWait(cpuInfo.getWait() + "%");
        return cpu;
    }

    /**
     * 设置 MEMORY 信息
     */
    private Memory getMemoryInfo(GlobalMemory globalMemory) {
        Memory memory = new Memory();
        memory.setTotalMem(PriUtil.jcmSize(globalMemory.getTotal()));
        memory.setUsedMem(PriUtil.jcmSize(globalMemory.getTotal() - globalMemory.getAvailable()));
        memory.setFreeMem(PriUtil.jcmSize(globalMemory.getAvailable()));
        return memory;
    }

    /**
     * 设置 DISK 信息
     */
    private List<Disk> getDisksInfo(OperatingSystem operatingSystem) {
        List<Disk> disks = new LinkedList<>();
        FileSystem fileSystem = operatingSystem.getFileSystem();
        List<OSFileStore> fsArray = fileSystem.getFileStores();
        Disk disk;
        for (OSFileStore fs : fsArray) {
            long free = fs.getUsableSpace();
            long total = fs.getTotalSpace();
            long used = total - free;
            disk = new Disk();
            disk.setDirName(fs.getLabel());
            disk.setSysTypeName(fs.getType());
            disk.setTypeName(fs.getName());
            disk.setTotal(PriUtil.diskSize(total));
            disk.setFree(PriUtil.diskSize(free));
            disk.setUsed(PriUtil.diskSize(used));
            if (total != 0) {
                disk.setUsage(NumberUtil.decimalFormat("#.##%", NumberUtil.div(used, total)));
            }
            disks.add(disk);
        }
        return disks;
    }

    /**
     * 设置 PROJECT 信息
     */
    private Project getProjectInfo() {
        return new Project();
    }
}
